from merchant.utils import post_data, Response

class GatewayConfigError(Exception):
    pass

class Gateway(object):

    LIVE = "live"
    TEST = "test"

    money_format = 'dollars'
    supported_cardtypes = []
    options = {}
    required = []

    def __init__(self, **kwargs):
        self.gateway_mode = kwargs.pop('gateway_mode', Gateway.LIVE)
        if not all([ r in kwargs for r in self.__class__.required]):
            raise GatewayConfigError("Not all required arguments were provided.  %s requires %s." %
                (self.__class__.__name__, ", ".join(self.__class__.required)))
        for name, value in kwargs.items():
            setattr(self, name, value)

    def supports(self, card_type):
        return (card_type in self.supported_cardtypes)
    
    def is_test(self):
        return self.gateway_mode == Gateway.TEST

    def amount(self, money):
        if money is None:
            return None
        try:
            cents = money.cents
        except AttributeError:
            cents = money

        if type(money) == '' or int(cents) < 0:
            raise TypeError, 'money amount must be either a Money ojbect or a positive integer in cents.'

        if self.money_format == 'cents':
            return str(cents)
        return ("%.2f" % (float(cents) / 100))

    def currency(money):
        try:
            return money.currency
        except AttributeError:
            return self.default_currency

    def purchase(self, money, creditcard, **kwargs):
        raise NotImplementedError

    def authorize(self, money, creditcard, **kwargs):
        raise NotImplementedError

    def capture(self, money, authorization, **kwargs):
        raise NotImplementedError

    def void(self, identification, **kwargs):
        raise NotImplementedError

    def credit(self, money, identification, **kwargs):
        raise NotImplementedError

    def recurring(self, money, creditcard, **kwargs):
        raise NotImplementedError
        
    def store(self, creditcard, **kwargs):
        raise NotImplementedError

    def unstore(self, indentification, **kwargs):
        raise NotImplementedError

    def require(self, kwargs_hash, *args):
        for arg in args:
            assert(kwargs_hash.has_key[arg])
            
    def _commit(self, params):
        "This is called by each operation (authorize, purchase, capture, void)"
        params = self._build_data(params)
        return self._submit_data(params)
            
    def _build_data(self, params):
        "Hook that lets a Gateway modify data before it's posted."
        return params
        
    def _submit_data(self, params):
        "Submits collected data to the endpoint URL."
        if self.is_test():
            print '\nSending BeanstreamGateway({'
            for k in sorted(params.keys()):
                print '\t%s = %s' % (k, params[k])
            print '})\n'
        raw_response = post_data(self.__class__.ENDPOINT_URL, params)
        if self.is_test():
            print '\nResponse({'
            for k in sorted(raw_response.keys()):
                print '\t%s = %s' % (k, raw_response[k])
            print '})\n'
        return self._build_response(raw_response)
        
    def _build_response(self, raw_response):
        return raw_response